package com.cw.lang.redis.service.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.BulkMapper;
import org.springframework.data.redis.core.query.SortQuery;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.util.CollectionUtils;

import com.cw.lang.redis.service.RedisForGeoService;
import com.cw.lang.redis.service.RedisForHashService;
import com.cw.lang.redis.service.RedisForListService;
import com.cw.lang.redis.service.RedisForSetService;
import com.cw.lang.redis.service.RedisForValueService;
import com.cw.lang.redis.service.RedisForZSetService;
import com.cw.lang.redis.service.RedisService;

import lombok.Getter;
import lombok.Setter;

/**
 * @author chenw
 * @version $$Id: RedisServiceImpl.java, v 0.1 2018/10/18 下午6:52 chenw Exp $$
 */
@Getter
@Setter
public class RedisServiceImpl<K extends Serializable, V extends Serializable> extends AbstractRedisService<K, V>
    implements RedisService<K, V> {

    private RedisForGeoService<K, V> redisForGeoService;

    private RedisForListService<K, V> redisForListService;

    private RedisForSetService<K, V> redisForSetService;

    private RedisForValueService<K, V> redisForValueService;

    private RedisForZSetService<K, V> redisForZSetService;

    private RedisForHashService<K, ?, ?> redisForHashService;

    @SuppressWarnings("unchecked")
    @Override
    public <HK, HV> RedisForHashService<K, HK, HV> opsForHash() {
        return (RedisForHashService<K, HK, HV>) redisForHashService;
    }

    @Override
    public RedisForGeoService<K, V> opsForGeo() {
        return redisForGeoService;
    }

    @Override
    public RedisForListService<K, V> opsForList() {
        return redisForListService;
    }

    @Override
    public RedisForSetService<K, V> opsForSet() {
        return redisForSetService;
    }

    @Override
    public RedisForValueService<K, V> opsForValue() {
        return redisForValueService;
    }

    @Override
    public RedisForZSetService<K, V> opsForZSet() {
        return redisForZSetService;
    }

    @Override
    public Boolean hasKey(K key) {
        return getRedisTemplate(key).hasKey(key);
    }

    @Override
    public Boolean delete(K key) {
        return getRedisTemplate(key).delete(key);
    }

    @Override
    public Long delete(Collection<K> keys) {
        if (CollectionUtils.isEmpty(keys)) {
            return 0L;
        } else {
            return getRedisTemplate(keys.iterator()
                .next()).delete(keys);
        }
    }

    @Override
    public DataType type(K key) {
        return getRedisTemplate(key).type(key);
    }

    @Override
    public Set<K> keys(K pattern) {
        return getRedisTemplate(pattern).keys(pattern);
    }

    @Override
    public K randomKey() {
        return getRedisTemplate().randomKey();
    }

    @Override
    public void rename(K oldKey, K newKey) {
        getRedisTemplate(oldKey).rename(oldKey, newKey);
    }

    @Override
    public Boolean renameIfAbsent(K oldKey, K newKey) {
        return getRedisTemplate(oldKey).renameIfAbsent(oldKey, newKey);
    }

    @Override
    public Boolean expire(K key, long timeout, TimeUnit unit) {
        return getRedisTemplate(key).expire(key, timeout, unit);
    }

    @Override
    public Boolean expireAt(K key, Date date) {
        return getRedisTemplate(key).expireAt(key, date);
    }

    @Override
    public Boolean persist(K key) {
        return getRedisTemplate(key).persist(key);
    }

    @Override
    public Boolean move(K key, int dbIndex) {
        return getRedisTemplate(key).move(key, dbIndex);
    }

    @Override
    public byte[] dump(K key) {
        return getRedisTemplate(key).dump(key);
    }

    @Override
    public void restore(K key, byte[] value, long timeToLive, TimeUnit unit) {
        getRedisTemplate(key).restore(key, value, timeToLive, unit);
    }

    @Override
    public Long getExpire(K key) {
        return getRedisTemplate(key).getExpire(key);
    }

    @Override
    public Long getExpire(K key, TimeUnit timeUnit) {
        return getRedisTemplate(key).getExpire(key, timeUnit);
    }

    @Override
    public List<V> sort(SortQuery<K> query) {
        return getRedisTemplate(query.getKey()).sort(query);
    }

    @Override
    public <T> List<T> sort(SortQuery<K> query, RedisSerializer<T> resultSerializer) {
        return getRedisTemplate(query.getKey()).sort(query, resultSerializer);
    }

    @Override
    public <T> List<T> sort(SortQuery<K> query, BulkMapper<T, V> bulkMapper) {
        return getRedisTemplate(query.getKey()).sort(query, bulkMapper);
    }

    @Override
    public <T, S> List<T> sort(SortQuery<K> query, BulkMapper<T, S> bulkMapper, RedisSerializer<S> resultSerializer) {
        return getRedisTemplate(query.getKey()).sort(query, bulkMapper, resultSerializer);
    }

    @Override
    public Long sort(SortQuery<K> query, K storeKey) {
        return getRedisTemplate(query.getKey()).sort(query, storeKey);
    }

    @Override
    public void watch(K key) {
        getRedisTemplate(key).watch(key);
    }

    @Override
    public void watch(Collection<K> keys) {
        getRedisTemplate().watch(keys);
    }

    @Override
    public void unwatch() {
        getRedisTemplate().unwatch();
    }

    @Override
    public void multi() {
        getRedisTemplate().multi();
    }

    @Override
    public void discard() {
        getRedisTemplate().discard();
    }

    @Override
    public List<Object> exec() {
        return getRedisTemplate().exec();
    }
}
